package com.sxf.biz.customer.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sxf.auth.enums.*;
import com.sxf.auth.login.service.UserService;
import com.sxf.auth.login.vo.AddCoordinateApproverReq;
import com.sxf.auth.login.vo.AddUserRes;
import com.sxf.auth.login.vo.UpdateUserStatusReq;
import com.sxf.biz.customer.dao.*;
import com.sxf.biz.customer.vo.*;
import com.sxf.biz.model.*;
import com.sxf.biz.operator.vo.OpSettleListReq;
import com.sxf.common.enums.ErrorCodeEnum;
import com.sxf.common.exceptions.BusinessException;
import com.sxf.common.param.BaseVO;
import com.sxf.consts.CodeTypeEnum;
import com.sxf.core.db.page.Pagination;
import com.sxf.utils.CodeUtils;
import com.sxf.utils.YtUtil;
import io.jsonwebtoken.lang.Collections;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description: TODO
 * @Author Leo
 * @date 2024/3/1920:56
 */
@Service
public class CustomerService extends ServiceImpl<CustomerMapper,Customer> {

    Logger logger = LoggerFactory.getLogger(CustomerService.class);

    private static final String ACCOUT_PATTERN = "^\\w+[\\w-\\.]*@\\w+[\\w\\.]*$";
    //    private static final String ACCOUT_PATTERN = "^([a-zA-Z0-9]+)@([a-zA-Z0-9.]+)$";
    private static final String ALIAS_PATTERN = "^\\w+[\\w\\.]*$";
//    private static final String ALIAS_PATTERN = "^[a-zA-Z0-9.]+$";

    @Autowired
    CustomerStaffMapper customerStaffMapper;
    @Autowired
    CenterMapper centerMapper;
    @Autowired
    UserService userService;
    @Autowired
    ProjectMapper projectMapper;

    @Autowired
    SettleMapper settleMapper;

    @Autowired
    ProjectCenterMapper projectCenterMapper;

    @Autowired
    ProjectCenterSubjectsMapper projectSubjectsMapper;

    @Autowired
    CustomerMapper customerMapper;

    @Autowired
    ProjectCenterAuditMapper projectCenterAuditMapper;

    @Autowired
    ProjectCenterCoordinatorMapper projectCenterCoordinatorMapper;

    @Autowired
    ProjectCenterSubjectsMapper projectCenterSubjectsMapper;

    @Autowired
    SettleStatusMapper settleStatusMapper;

    @Autowired
    CodeUtils codeUtils;

    /**
     *
     * @param req
     * @return
     */
    public Pagination<StaffListRes> getCustomerStaffByPage(StaffListReq req) {
        Customer customer = getOne(new QueryWrapper<Customer>().lambda().eq(Customer::getPkAdmin, req.getUserId()).last(" limit 1"));
        if(customer == null){
            throw new BusinessException(ErrorCodeEnum.CUSTOMER_NOT_EXIST_ERROR);
        }
        req.setPkCustomer(customer.getPkCustomer());
        return customerStaffMapper.getStaffListByPage(new Pagination<>(req), req);
    }

    public AddUserRes addCustomerStaff(AddCoordinateApproverReq req) {

        /**
         * 账号校验
         * 协调员：手机号+密码登录
         * 审核员：账号+密码
         */
        Customer customer = authValidation(req.getUserId());
        if(StaffTypeEnum.APPROVE.getCode().equals(req.getStaffType())){
            if(!YtUtil.validStrPattern(ACCOUT_PATTERN,req.getAccount())){
                throw new BusinessException("人员账号格式需要满足数字字母+@+客户账号后缀");
            }
            String[] accounts = req.getAccount().split("@");
            if(accounts.length != 2){
                throw new BusinessException("人员账号格式需要满足数字字母+@+客户账号后缀");
            }

            if(!customer.getCustomerAlias().equals(accounts[1])){
                throw new BusinessException("人员账号后缀必须和客户账号后缀[" + customer.getCustomerAlias() + "]保持一致");
            }
        }else{
            req.setAccount(req.getUserMobile());
        }
        req.setPkCustomer(customer.getPkCustomer());
        return userService.addCoorUser(req);
    }

    public Boolean toggleUserStatus(ToggleStaffReq req) {
        UpdateUserStatusReq param = new UpdateUserStatusReq();
        BeanUtils.copyProperties(req,param);
        Customer customer = customerMapper.selectOne(new QueryWrapper<Customer>().lambda().eq(Customer::getPkAdmin, req.getUserId()));
        if(customer == null){
            throw new BusinessException(ErrorCodeEnum.CUSTOMER_NOT_EXIST_ERROR);
        }
        param.setPkCustomer(customer.getPkCustomer());
        return userService.updateUserStatus(param);
    }

    public Pagination<CenterListRes> getCenterListByPage(CenterListReq req){
        Pagination<CenterListRes> centerListByPage = centerMapper.getCenterListByPage(new Pagination<>(req), req);
        if(req.getPkProject() != null){
            List<ProjectCenterStaticRes> subjectsCenterStatic = centerMapper.getSubjectsCenterStatic(req.getPkProject());
            Map<Long,Integer> subjectsMap = new HashMap<>();
            for(ProjectCenterStaticRes pcs:subjectsCenterStatic){
                subjectsMap.put(pcs.getPkCenter(),pcs.getSubjectsCount());
            }
            for(CenterListRes res: centerListByPage.getDataset()){
                res.setExistSubjectsCount(subjectsMap.get(res.getPkCenter()));
            }
        }
        return centerListByPage;
    }

    public Boolean addCenter(AddCenterReq req){
        Customer customer = authValidation(req.getUserId());
        Center center = new Center();
        center.setPkCustomer(customer.getPkCustomer());
        center.setCenterName(req.getCenterName());
        center.setCityName(req.getCityName());
        center.setAddress(req.getAddress());
        center.setCreator(req.getUserId());
        center.setCreatorName(req.getCurName());
        center.setCreatedTime(new Date());
        return centerMapper.insert(center) > 0 ;
    }

    public Boolean deleteCenter(CenterDeleteReq req){
        Customer customer = authValidation(req.getUserId());

        Center center1 = centerMapper.selectById(req.getPkCenter());
        if(center1 == null){
            throw new BusinessException("该中心不存在");
        }
        QueryWrapper<ProjectCenter> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ProjectCenter::getPkCenter,req.getPkCenter());
        Integer count = projectCenterMapper.selectCount(queryWrapper);
        if(count > 0){
            throw new BusinessException("该中心已绑定项目，不能删除");
        }
        return centerMapper.deleteById(req.getPkCenter()) > 0;
    }

    public ProjectCenterDetailRes getProjectCenterDetail(ProjectCenterDetailReq req){
        ProjectCenterDetailRes projectCenterDetail = centerMapper.getProjectCenterDetail(req);
        //结算
        SettleListReq slr = new SettleListReq();
        slr.setUserId(req.getUserId());
        slr.setPkProject(projectCenterDetail.getPkProject());
        slr.setPkCenter(projectCenterDetail.getPkCenter());
        SettleStaticsResVo settleStatics = settleMapper.getSettleStatics(slr);
        if(settleStatics != null){
            projectCenterDetail.setSettledMny(settleStatics.getSettledMny()==null?BigDecimal.ZERO:settleStatics.getSettledMny());
            projectCenterDetail.setUnsettledMny(settleStatics.getUnsettleMny()==null?BigDecimal.ZERO:settleStatics.getUnsettleMny());
        }
        //受试者
        QueryWrapper<ProjectCentersSubjects> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ProjectCentersSubjects::getPkProject,projectCenterDetail.getPkProject())
                .eq(ProjectCentersSubjects::getPkCenter,projectCenterDetail.getPkCenter());
        Integer count = projectCenterSubjectsMapper.selectCount(queryWrapper);
        projectCenterDetail.setExistSubjectsCount(count);

        //协调者
        List<ProjectCenterCoordinatorAudit> coordinators = projectCenterMapper.getCoordinatorList(projectCenterDetail.getPkProjectCenter());
        projectCenterDetail.setCoordinators(coordinators);
        List<ProjectCenterCoordinatorAudit> auditList = projectCenterMapper.getAuditList(projectCenterDetail.getPkProjectCenter());
        projectCenterDetail.setAudits(auditList);
        return projectCenterDetail;
    }


    public Pagination<ProjectListRes> getProjectListByPage(ProjectListReq req){
        Pagination<ProjectListRes> projectListByPage = projectMapper.getProjectListByPage(new Pagination<>(req), req);
        return projectListByPage;
    }

    public ProjectDetailRes getProjectDetail(ProjectDetailReq req){
        Project project = projectMapper.selectById(req.getPkProject());
        if(project == null){
            throw new BusinessException(ErrorCodeEnum.PROJECT_NOT_EXIST_ERROR);
        }
        if(!UserTypeEnum.PLATFORM.getCode().equals(req.getClient())){
            Customer customer = authValidation(req.getUserId());
            if(!project.getPkCustomer().equals(customer.getPkCustomer())){
                throw new BusinessException(ErrorCodeEnum.PROJECT_NOT_EXIST_ERROR);
            }
        }
        ProjectDetailRes res = new ProjectDetailRes();
        BeanUtils.copyProperties(project,res);
        //结算单信息
        if(!ProjectStatusEnum.UN_START.getCode().equals(project.getStatus())){
            SettleStaticsResVo settleStatics = new SettleStaticsResVo();
            if(UserTypeEnum.PLATFORM.getCode().equals(req.getClient())){
                OpSettleListReq olr = new OpSettleListReq();
                olr.setPkProject(req.getPkProject());
                settleStatics = settleMapper.getSettleStatics4Op(olr);
            } else {
                SettleListReq slr = new SettleListReq();
                slr.setUserId(req.getUserId());
                slr.setPkProject(req.getPkProject());
                settleStatics = settleMapper.getSettleStatics(slr);
            }
            if(settleStatics != null){
                res.setSettledMny(settleStatics.getSettledMny()==null?BigDecimal.ZERO:settleStatics.getSettledMny());
                res.setUnsettleMny(settleStatics.getUnsettleMny()==null?BigDecimal.ZERO:settleStatics.getUnsettleMny());
            }
        }
        //
        Integer count = projectCenterMapper.selectCount(new QueryWrapper<ProjectCenter>().lambda().eq(ProjectCenter::getPkProject, req.getPkProject()));
        res.setExistCenterCount(count);
        //
        Integer subjectCount = projectSubjectsMapper.selectCount(new QueryWrapper<ProjectCentersSubjects>().lambda()
                .eq(ProjectCentersSubjects::getPkProject, req.getPkProject()).ne(ProjectCentersSubjects::getBindStatus, ProjectSubjectsProgressEnum.QUIT.getCode()));
        res.setExistSubjectsCount(subjectCount);
        return res;
    }


    public AddProjectRes addProject(AddProjectReq req){
        Customer customer = authValidation(req.getUserId());
        QueryWrapper<Project> projectQueryWrapper = new QueryWrapper<>();
        projectQueryWrapper.lambda().eq(Project::getProjectName,req.getProjectName())
                .eq(Project::getPkCustomer,customer.getPkCustomer());
        List<Project> projects = projectMapper.selectList(projectQueryWrapper);
        if(projects != null && projects.size() > 0){
            throw new BusinessException(ErrorCodeEnum.PROJECT_EXIST_ERROR);
        }
        Project project = new Project();
        BeanUtils.copyProperties(req,project);
        if(project.getProjectAlias() != null){
            if(project.getProjectAlias().length() > 50){
                throw new BusinessException("项目简称长度不能大于50");
            }
        }
        project.setProjectCode(codeUtils.getCode(CodeTypeEnum.PROJECT));
        project.setPkCustomer(customer.getPkCustomer());
        project.setCreator(req.getUserId());
        project.setCreatorName(req.getCurName());
        project.setCreatedTime(new Date());
        if (req.getStartDate().after(DateUtil.beginOfDay(new Date()))) {
            project.setStatus(ProjectStatusEnum.UN_START.getCode());
        }else{
            project.setStatus(ProjectStatusEnum.IN_PROGRESS.getCode());
        }
        projectMapper.insert(project);
        AddProjectRes res = new AddProjectRes();
        res.setPkProject(project.getPkProject());
        return res;
    }

    public Boolean editProject(EditProjectReq req){
        Customer customer = authValidation(req.getUserId());

        Project project = projectMapper.selectById(req.getPkProject());
        if(ObjectUtil.isNull(project)){
            throw new BusinessException(ErrorCodeEnum.PROJECT_NOT_EXIST_ERROR);
        }
        BeanUtils.copyProperties(req,project);
        project.setModifier(req.getUserId());
        project.setModifierName(req.getCurName());
        project.setModifiedTime(new Date());
        return projectMapper.updateById(project)>0;
    }

    public Boolean finishProject(ProjectDetailReq req){
        authValidation(req.getUserId());
        Project project = projectMapper.selectById(req.getPkProject());
        if(ObjectUtil.isNull(project)){
            throw new BusinessException(ErrorCodeEnum.PROJECT_NOT_EXIST_ERROR);
        }

        project.setStatus(ProjectStatusEnum.COMPLETED.getCode());
        project.setModifier(req.getUserId());
        project.setModifierName(req.getCurName());
        project.setModifiedTime(new Date());
        return projectMapper.updateById(project) > 0;
    }

    public Pagination<SubjectsListRes> getSubjectList(SubjectListReq req){
        Pagination<SubjectsListRes> subjectListByPage = customerMapper.getSubjectListByPage(new Pagination<>(req),req);
        return subjectListByPage;
    }

    public Pagination<CenterListRes> getCenterList(CenterListReq req){
        return centerMapper.getCenterListByPage(new Pagination<>(req),req);
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean addCenter4project(AddCenterForProjectReq req){
        Customer customer = authValidation(req.getUserId());
        Project project = projectMapper.selectById(req.getPkProject());
        if(project == null){
            throw new BusinessException(ErrorCodeEnum.PROJECT_NOT_EXIST_ERROR);
        }
        Center center = centerMapper.selectById(req.getPkCenter());
        if(center == null){
            throw new BusinessException(ErrorCodeEnum.CENTER_NOT_EXIST_ERROR);
        }

        QueryWrapper<ProjectCenter> projectCenterQueryWrapper = new QueryWrapper<>();
        projectCenterQueryWrapper.lambda().eq(ProjectCenter::getPkProject,req.getPkProject()).eq(ProjectCenter::getPkCenter,req.getPkCenter());
        List<ProjectCenter> projectCenters = projectCenterMapper.selectList(projectCenterQueryWrapper);
        if(projectCenters != null && projectCenters.size() > 0){
            throw new BusinessException("该中心已绑定该项目");
        }

        ProjectCenter pc = new ProjectCenter();
        pc.setPkCenter(req.getPkCenter());
        pc.setPkProject(req.getPkProject());
        pc.setPkCustomer(customer.getPkCustomer());
//        pc.setCoordinatorId(req.getCoordinatorId());
        pc.setSubjectsCount(req.getSubjectsCount());
        pc.setStatus(CommonStatusEnum.VALID.getCode());
        pc.setCreatedTime(new Date());
        pc.setCreator(req.getUserId());
        pc.setCreatorName(req.getCurName());
        projectCenterMapper.insert(pc);
        if(req.getCoordinatorIds() != null && req.getCoordinatorIds().size() > 0){
            for(String coordinatorId : req.getCoordinatorIds()){
                ProjectCenterCoordinator coor = new ProjectCenterCoordinator();
                coor.setCoordinatorId(coordinatorId);
                coor.setPkProjectCenter(pc.getPkProjectCenter());
                projectCenterCoordinatorMapper.insert(coor);
            }
        }
        if(req.getAuditIds() != null && req.getAuditIds().size() > 0){
            for (int i = 0; i < req.getAuditIds().size() ; i++) {
                ProjectCenterAudit pca = new ProjectCenterAudit();
                pca.setFlowOrder(i);
                pca.setAuditId(req.getAuditIds().get(i));
                pca.setPkProjectCenter(pc.getPkProjectCenter());
                projectCenterAuditMapper.insert(pca);
            }
        }
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean editCenter4project(EditCenterForProjectReq req){
        Customer customer = authValidation(req.getUserId());
        ProjectCenter pc = projectCenterMapper.selectById(req.getPkProjectCenter());
        if(pc == null){
            throw new BusinessException("项目和中心关系已经不存在");
        }
        if(req.getPkProject() != null){
            Project project = projectMapper.selectById(req.getPkProject());
            if(project == null){
                throw new BusinessException(ErrorCodeEnum.PROJECT_NOT_EXIST_ERROR);
            }
            pc.setPkProject(req.getPkProject());
        }
        if(req.getPkCenter() != null){
            Center center = centerMapper.selectById(req.getPkCenter());
            if(center == null){
                throw new BusinessException(ErrorCodeEnum.CENTER_NOT_EXIST_ERROR);
            }
            pc.setPkCenter(req.getPkCenter());
        }

//        pc.setPkCustomer(customer.getPkCustomer());
//        pc.setCoordinatorId(req.getCoordinatorId());
        pc.setSubjectsCount(req.getSubjectsCount());
//        pc.setStatus(CommonStatusEnum.VALID.getCode());
        pc.setModifiedTime(new Date());
        pc.setModifier(req.getUserId());
        pc.setModifierName(req.getCurName());
        projectCenterMapper.updateById(pc);
        if(req.getCoordinatorIds() != null && req.getCoordinatorIds().size() > 0){
            QueryWrapper<ProjectCenterCoordinator> pccWrapper = new QueryWrapper<>();
            pccWrapper.lambda().eq(ProjectCenterCoordinator::getPkProjectCenter,pc.getPkProjectCenter());
            projectCenterCoordinatorMapper.delete(pccWrapper);
            for(String coordinatorId : req.getCoordinatorIds()){
                ProjectCenterCoordinator coor = new ProjectCenterCoordinator();
                coor.setCoordinatorId(coordinatorId);
                coor.setPkProjectCenter(pc.getPkProjectCenter());
                projectCenterCoordinatorMapper.insert(coor);
            }
        }
        if(req.getAuditIds() != null && req.getAuditIds().size() > 0){
            if(existInprogressSettles(req.getPkProject(),req.getPkCenter())){
                throw new BusinessException("该项目机构下存在审批中的结算单，请确保所有结算单都已经完成后再重试！");
            }
            QueryWrapper<ProjectCenterAudit> pcaWrapper = new QueryWrapper<>();
            pcaWrapper.lambda().eq(ProjectCenterAudit::getPkProjectCenter,pc.getPkProjectCenter());
            projectCenterAuditMapper.delete(pcaWrapper);
            for (int i = 0; i <req.getAuditIds().size() ; i++) {
                ProjectCenterAudit pca = new ProjectCenterAudit();
                pca.setFlowOrder(i);
                pca.setAuditId(req.getAuditIds().get(i));
                pca.setPkProjectCenter(pc.getPkProjectCenter());
                projectCenterAuditMapper.insert(pca);
            }
        }
        return true;
    }

    public SettlePageRes getSettleListByPage(SettleListReq req){
        SettlePageRes res = new SettlePageRes();
        Pagination<SettleListRes> settleListByPage = settleMapper.getSettleListByPage(new Pagination<>(req),req);
        res.setSettleList(settleListByPage);
        //汇总
        SettleStaticsResVo settleStatics = settleMapper.getSettleStatics(req);
        if(settleStatics != null){
            if(settleStatics.getUnsettleMny() == null){
                settleStatics.setUnsettleMny(BigDecimal.ZERO);
            }
            if(settleStatics.getSettledMny() == null){
                settleStatics.setSettledMny(BigDecimal.ZERO);
            }
            res.setSettledTotalMny(settleStatics.getSettledMny());
            res.setUnsettledTotalMny(settleStatics.getUnsettleMny());
            res.setTotalMny(settleStatics.getSettledMny().add(settleStatics.getUnsettleMny()));
        }
        return res;
    }

    public SettleDetailRes getSettleDetail(SettleDetailReq req){
        SettleDetailRes res = new SettleDetailRes();

        Settle settle = settleMapper.selectById(req.getPkSettle());
        if(settle == null){
            throw new BusinessException(ErrorCodeEnum.SETTLE_NOT_EXIST_ERROR);
        }

        BeanUtils.copyProperties(settle,res);
        if(!StringUtils.isEmpty(settle.getImgs())){
            String[] imgList = settle.getImgs().split(";");
            res.setImgList(Arrays.asList(imgList));
        }
        List<SettleStatusVo> list = getSettleStatus(req);
        res.setSettleStatus(list);
        return res;

    }

    public Boolean addSettleStatus(Settle settle, BaseVO baseVO, String comments){
        SettleStatus ss = new SettleStatus();
        ss.setPkSettle(settle.getPkSettle());
        ss.setCreator(baseVO.getUserId());
        ss.setCreatorName(baseVO.getCurName());
        ss.setCreatedTime(new Date());
        ss.setStatus(settle.getStatus());
        ss.setRemark(comments);
//        if(SettleStatusEnum.CHECKING.getCode().equals(settle.getStatus())){
//        }else if(SettleStatusEnum.REJECTED.getCode().equals(settle.getStatus())
//                ||SettleStatusEnum.FAILED.getCode().equals(settle.getStatus())){
//            ss.setRemark(settle.getRejectReason());
//        }
        return settleStatusMapper.insert(ss) > 0;
    }

    public List<SettleStatusVo> getSettleStatus(SettleDetailReq req) {
        List<SettleStatusVo> list = null;
        QueryWrapper<SettleStatus> settleStatusQueryWrapper = new QueryWrapper<>();
        settleStatusQueryWrapper.lambda().eq(SettleStatus::getPkSettle,req.getPkSettle()).orderByDesc(SettleStatus::getPkStatus);
        List<SettleStatus> settleStatuses = settleStatusMapper.selectList(settleStatusQueryWrapper);
        if(!Collections.isEmpty(settleStatuses)){
            list = settleStatuses.stream().map(s->{
                SettleStatusVo vo = new SettleStatusVo();
                vo.setStatus(s.getStatus());
                vo.setCreatedTime(s.getCreatedTime());
                vo.setCreatorName(s.getCreatorName());
                vo.setRemark(s.getRemark());
                return vo;
            }).collect(Collectors.toList());
        }
        return list;
    }

    public Pagination<SubjectsListRes> getSubjectsByPage(SubjectListReq req){
        Pagination<SubjectsListRes> subjectListByPage = customerMapper.getSubjectListByPage(new Pagination<>(req), req);
        return subjectListByPage;
    }

    public List<StaffInfoDetaiVo> getStaffInfoByPkUser(String pkUser){
        List<StaffInfoDetaiVo> staffInfoByPkUser = customerMapper.getStaffInfoByPkUser(pkUser);
        return staffInfoByPkUser;
    }

    private Customer authValidation(String userId) {
        QueryWrapper<Customer> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Customer::getPkAdmin,userId);
        List<Customer> list = list(queryWrapper);
        if(list == null || list.size() == 0){
            throw new BusinessException(ErrorCodeEnum.PERMISSION_ERROR);
        }
        return list.get(0);
    }

    private Boolean existInprogressSettles(Long pkProject,Long pkCenter){
        QueryWrapper<Settle> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Settle::getPkProject,pkProject)
                .eq(Settle::getPkCenter,pkCenter)
                .eq(Settle::getStatus,SettleStatusEnum.CHECKING.getCode());
        List<Settle> settles = settleMapper.selectList(queryWrapper);
        if(settles != null && settles.size() > 0){
            return true;
        }
        return false;
    }

}
